package com.oceansoft.core.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.EmptyFileFilter;

/**
 * Zip处理
 * 
 * @author Administrator
 * 
 */
public final class ZipUtil {
	static final int BUFFER = 2048;
	static boolean flag = false;

	public static void zip(File inputFile, File outputFile) throws IOException {
		ZipOutputStream output = null;
		try {
			output = new ZipOutputStream(new FileOutputStream(outputFile));
			if (inputFile.isDirectory()) {
				String basePath = inputFile.getParent();
				Collection<?> files = FileUtils.listFiles(inputFile, EmptyFileFilter.EMPTY, EmptyFileFilter.EMPTY);
				Iterator<?> iterator = files.iterator();
				while (iterator.hasNext()) {
					File file = (File) iterator.next();
					String relativePath = FilenameUtil.getRelativePath(basePath, file.getAbsolutePath());
					if ((relativePath.charAt(0) == '\\') || (relativePath.charAt(0) == '/')) {
						relativePath = relativePath.substring(1);
					}
					FileInputStream input = new FileInputStream(file);
					output.putNextEntry(new ZipEntry(relativePath));
					try {
						IOUtils.copy(input, output);
					} catch (Exception e) {
					} finally {
						IOUtils.closeQuietly(input);
					}
				}
			} else {
				FileInputStream input = new FileInputStream(inputFile);
				output.putNextEntry(new ZipEntry(inputFile.getName()));
				IOUtils.copy(input, output);
				IOUtils.closeQuietly(input);
			}
		} finally {
			IOUtils.closeQuietly(output);
		}
	}

	public static File ZipSubdirectory(File myDir) throws IOException {
		// 创建缓冲输入流BufferedInputStream
		BufferedInputStream origin = null;
		// 创建ZipOutputStream对象，将向它传递希望写入文件的输出流
		File zipFile = new File("D:/" + myDir.getName() + ".zip");
		FileOutputStream fos = new FileOutputStream(zipFile);
		ZipOutputStream out = new ZipOutputStream((OutputStream) (new BufferedOutputStream(fos, BUFFER)));
		// dirContents[]获取当前目录(myDir)所有文件对象（包括子目录名)
		File dirContents[] = myDir.listFiles();
		// 创建临时文件tempFile,使用后删除
		File tempFile = null;
		try {
			// 处理当前目录所有文件对象，包括子目录
			for (int i = 0; i < dirContents.length; i++) {
				// 使用递归方法将当前目录的子目录转成一个ZIP文件，并作为一个ENTRY加进"ORIGIN"
				if (dirContents[i].isDirectory()) {
					tempFile = ZipSubdirectory(dirContents[i]);
					flag = true;
				}
				// 如果当前文件不是子目录
				else {
					tempFile = dirContents[i];
					// flag标记tempFile是否由子目录压缩成的ZIP文件
					flag = false;
				}
				System.out.println("Compress file: " + tempFile.getName());
				FileInputStream fis = new FileInputStream(tempFile);
				origin = new BufferedInputStream(fis, BUFFER);
				// 为被读取的文件创建压缩条目
				ZipEntry entry = new ZipEntry(tempFile.getName());
				byte data[] = new byte[BUFFER];
				int count;
				// 在向ZIP输出流写入数据之前，必须首先使用out.putNextEntry(entry); 方法安置压缩条目对象
				out.putNextEntry(entry);
				// 向ZIP 文件写入数据
				while ((count = origin.read(data, 0, BUFFER)) != -1) {
					out.write(data, 0, count);
				}
				// tempFile是临时生成的ZIP文件,删除它
				if (flag == true) {
					flag = tempFile.delete();
					System.out.println("Delete file:" + tempFile.getName() + flag);
				}
				// 关闭输入流
				origin.close();
			}
			out.close();
		} catch (Exception e) {
			System.out.println(e);
		}
		// 递归返回
		return zipFile;
	}

	// 将流文件压缩到指定的zip文件中
	public static File InputStream2ZIP(String tempFile, Map<String, InputStream> map) throws IOException {
		// 创建缓冲输入流BufferedInputStream
		BufferedInputStream origin = null;
		// 创建ZipOutputStream对象，将向它传递希望写入文件的输出流
		File zipFile = new File(tempFile);
		FileOutputStream fos = new FileOutputStream(zipFile);
		ZipOutputStream out = new ZipOutputStream((OutputStream) (new BufferedOutputStream(fos, BUFFER)));

		Set<String> keySet = map.keySet();
		Iterator<String> it = keySet.iterator();
		while (it.hasNext()) {
			String name = it.next();
			InputStream ins = map.get(name);
			origin = new BufferedInputStream(ins, BUFFER);
			// 为被读取的文件创建压缩条目
			ZipEntry entry = new ZipEntry(name);
			byte data[] = new byte[BUFFER];
			int count;
			// 在向ZIP输出流写入数据之前，必须首先使用out.putNextEntry(entry); 方法安置压缩条目对象
			out.putNextEntry(entry);
			// 向ZIP 文件写入数据
			while ((count = origin.read(data, 0, BUFFER)) != -1) {
				out.write(data, 0, count);
			}
		}
		// 关闭输入流
		origin.close();
		out.close();
		// 递归返回
		return zipFile;
	}

	// 将流文件保存到指定文件夹下
	public static void InputStream2File(String tempFilepath, Map<String, InputStream> map) throws IOException {
		// 创建缓冲输入流BufferedInputStream
		Set<String> keySet = map.keySet();
		Iterator<String> it = keySet.iterator();
		while (it.hasNext()) {
			String name = it.next();
			InputStream ins = map.get(name);
			InputStream2File(tempFilepath, name, ins);
		}

	}

	// 将流文件保存到指定文件夹下指定ming
	private static void InputStream2File(String dir, String filename, InputStream ins) {
		try {
			System.out.print("输入要保存文件的内容：");
			int n = 2048;
			byte buffer[] = new byte[n];
			// 读取标准输入流
			// count = list.get(0).read(buffer);// System.in.read(buffer);
			// 创建文件输出流对象
			FileOutputStream os = new FileOutputStream(dir + "\\" + filename);
			// 写入输出流
			int len = 0;
			while ((len = ins.read(buffer)) != -1) {

				os.write(buffer, 0, len);

			}
			// os.write(buffer, 0, count);
			// 关闭输出流
			os.close();
			System.out.println("已保存到" + dir + "\\" + filename);
		} catch (IOException ioe) {
			System.out.println(ioe);
		} catch (Exception e) {
			System.out.println(e);
		}

	}

	public static void closeQuietly(ZipFile zipFile) {
		if (zipFile == null)
			return;
		try {
			zipFile.close();
		} catch (Exception ignored) {
		}
	}

	public static int countOfZip(File zipFilename) {
		try {
			int size = 0;
			ZipFile zipFile = new ZipFile(zipFilename);
			Enumeration<?> en = zipFile.entries();
			ZipEntry zipEntry = null;
			while (en.hasMoreElements()) {
				zipEntry = (ZipEntry) en.nextElement();
				if (!(zipEntry.isDirectory()))
					;
				++size;
			}

			zipFile.close();
			return size;
		} catch (IOException e) {
		}
		return 0;
	}
}
